perm filename WISE.RES[UP,DOC] blob
sn#272450 filedate 1977-03-26 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00007 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 A FEW WORDS OF WISDOM
C00008 00003 THE MACRO FACILITY (General Discussion)
C00015 00004 ADDITIONAL COMMANDS TO DESK CALCULATOR
C00018 00005 THE EDITOR
C00024 00006 THE MACRO LANGUAGE
C00039 00007 LANGUAGE SUMMARY
C00041 ENDMK
C⊗;
A FEW WORDS OF WISDOM
WISE is a rather fancy desk calculator which was written
originally by Bill Weiher and modified considerably by Dick Sweet.
It is a stack machine with 10 addressable registers and a stack
capable of containing 100 (decimal) entries. Visible on the screen
are the named registers and the top 6 elements of the stack.
The program runs on either a Data Disc, III, or Datamedia
display. You may move from one to the other if you type REE instead
of CON when you reattach. The REE command simply looks at the display
type, adjusts some tables if necessary, and then continues where you
left off. (Probably not true of Datamedias.)
The real power of the calculator comes from the macro facility.
WISE allows one to define up to 26 macros. These can take arguments
from the stack and can return multiple values on the stack. They can
also use the named registers or even request numbers to be typed in
by the user. Programs can be modified by an editor similar to SOS,
and can be saved and restored on the disk.
THE DESK CALCULATOR
WISE allows the user to do calculations with more accuracy
than SAIL and with less trouble than the LISP "bignum" package.
Arithmetic is done using scaled fixed point double word integers
and has an accuracy of 20 decimal digits and an exponent range
(i.e. power of ten) of between -99 and 99.
The screen shows the 10 registers, named A through J, and
the top 6 elements of the stack. It actually shows the bottom
6 elements since the stack is a "push-up stack", but for this
description, we will speak of the "top" of the stack, even though
it is displayed on the bottom.
As a new number is entered, it becomes the new top of
the stack. You can correct mistakes with the backspace key until
the number is the "official" top of stack. This happens when
a non-number-forming character such as an operator or a blank
is struck. At this time, the number is normalized and placed
onto the stack. To indicate a power of ten, enter the letter
"E", followed by the power of ten. Since "-" is a binary operator,
the character "<" is used to denote a unary minus when entering
a negative number. However, "-" is used for the power of ten
since the meaning is clear from context.
Numbers can be recalled to the top of the stack from the
named registers by simply typing the name of the register. This
is true not only for registers A-J, but also for the remainder
register R which is set by the integer divide operation. The
character "π" denotes pi to 20 significant digits.
OPERATORS:
These operators use the top two elements of the stack
and replace the operands by the result.
+ ADD top two elements
- SUBTRACT top from second
* MULTIPLY top two elements
/ DIVIDE top into second
\ DIVIDE second into top
% INTEGER DIVIDE top into second, remainder to R
& INTEGER DIVIDE second into top, remainder to R
↑ EXPONENTIATE, raise second to top power
FUNCTIONS:
The functions all operate on the top of the stack except ARCTAN2
which operates on the top two elements.
~ ROUND OFF to 15 significant digits
$ CHANGE SIGN
| ABSOLUTE VALUE
<meta>R SQUARE ROOT
<meta>S SINE
<meta>C COSINE
<meta>L LOG (to the base e)
<meta>E EXPONENTIAL
<meta>A ARCTANGENT
<meta>T ARCTAN2 (Arctangent of top divided by second)
MISCELLANEOUS OPERATIONS:
= DUPLICATE top of stack
X EXCHANGE top two elements
→<register name> STORE top of stack in register
or ←<reg name> (does not disturb stack)
> POP top of stack, never to be seen again
Z ZERO STACK
<form feed> REWRITE SCREEN
THE MACRO FACILITY (General Discussion)
In order to extend the power of the desk calculator, one can
define macro operations. There can be up to 26 macros defined at any
given time. Each macro has a single character name. One calls a macro
by typing the macro name with the <control> key held down. That is, to
call macro A, you type <control>A. Macros may take arguments from
the stack, or they may just operate on the named registers. Results
can be returned on the stack, either single or multiple results.
There are various operations available to compiled macros
which cannot be accessed by a person simply using the desk calculator.
These include the ability to branch, either conditionally or
unconditionally, several operations designed to simplify FOR statement
execution, and the ability to temporarily push items onto the system
pushdown stack, which allows the calculator stack to be rearranged
to some extent without effecting the named registers.
Programs variables are limited to the 10 named variables
A-J. However, there are provisions for saving these registers when
a macro (program) is entered. When program arguments are initially
stored in registers, the previous values of the registers are
automatically saved and then restored upon exit from the program.
Any other registers may be saved on entry and restored on exit
by using the NEW construction (see below).
Programs may use the stack as well as the named variables
for its operations. If a program statement is simply an expression,
its value is pushed on the stack. If a function, such as
SIN, is not followed by an argument in the source program, the compiled
program will use the top of the stack as the argument to the function.
There is even a "null" function "TOP" which simply returns the
top of the stack as its value. The multiple store operation is
used to store several stack elements into several registers.
However, a certain amount of care must be taken if the top of
the stack is used in expressions. The compiler parses the expressions
in a left to right fashion and places intermediate results on the
stack. Thus, if a function is used without arguments in some place other
than the first variable of an expression, the "top" of the stack will
probably be something other than what you plan it to be! For example:
4;A←2+SIN;
will compile as code to set A=4+sin(2).
Another limitation in using the stack is motivated by the
fact that programs use the stack for saving registers upon entry.
Any information that is on the stack at the end of a program must
be removed in order to get to the saved register values. This is
accomplished by remembering the status of the stack on entry and
"synchronizing" the stack on exit. Programs can return one or
more values on the stack by using the RETURN statement. In this
case, the RETURNed values are pushed onto the system stack, the
saved register values are restored, and the RETURNed values are
popped back onto the calculator stack. However, it should be
noted that the stack synchronization takes place BEFORE the
expressions are evaluated for the RETURN statement. If one does
has no RETURNed values, formal paramaters, or NEW variables, and
wishes to inhibit this stack synchronization, he can precede his
macro definition with the reserved word NOSYNC.
The compiler generates "code" in the form of a string of 9
bit characters, corresponding to the keyboard with <control> and
<meta> bits. During program execution, the calculator reads from
this string rather than from the keyboard. Several of the operation
routines, such as GO TO check to see that a macro is being executed
and are NO-OP's otherwise. It is possible to get the calculator to
stop reading from the string and go back to the keyboard in the
following manner:
Type <call> (↑C)
Type REE
The reentry routine simply zeroes the macro string pointer and
continues WISE where it was interrupted. There may be all
sorts of junk on the stack, such as saved register values, but
at least the keyboard will be back in control!
ADDITIONAL COMMANDS TO DESK CALCULATOR
The following commands are related to the macro
facility of WISE. They are recognized at the level of the
of the main control loop of WISE (i.e., they are not editor
commands).
Let αε{A,B,...,Z},
Mα Macro edit α. Call the editor, in insert mode if no
macro α already exists.
Sα Save macro text for α in a file names WISEα.MCR.
Lα Load the macro text for α from the file WISEα.MCR. If
there is already text for α, replace it.
Kα Compile α. This is not necessary, since macros are
automatically compiled the first time they are used.
However, it is useful for checking macro syntax.
T Text function. Enter the editor to create a temporary
macro that is compiled, executed, and forgotten immediately
upon exit from the editor.
Pα Print the generated code for α. This is of use mainly
for compiler debugging.
Q Reverse the value of the macro print toggle. Usually the
screen is locked during macro execution in order to speed
things up. Typing Q an odd number of times will allow one
to see the macro execution in all its gory detail. In any
case, the screen is unlocked at each PAUSE statement and
whenever an input is prompted by the IN function.
REE A system level command, given after typing <call>(↑C) that
terminates macro interpretation. It is also used when moving
a program from a III display to a Data Disk, or DD to III.
THE EDITOR
WISE contains a rather simple minded editor to allow
users to enter and correct macros. It is a line oriented editor
which resembles SOS, with several distinctions. The lines
have "floating" numbers. The first line is line 1, the next one 2,
and so forth. When new lines are inserted in the middle, the numbers
of the lines at the end increase. The following description should
be sufficient for using the editor.
SYNTAX:
<line number> ::= <integer> | . | *
<range> ::= <line number> | <line number>:<line number> |
<line number>!<integer>
<command> ::= <insert> | <delete> | <print> | <alter> | <join> | <find> |
<exit> | <quit> | <nextline> | <prevline> | <prntdot> |
<rename>
<insert> ::= I<line number>
<delete> ::= D<range>
<print> ::= P | P<range>
<alter> ::= Z<line number>
<join> ::= J<line number>
<find> ::= F<string><alt mode><range> | F<string><alt mode> | F
<exit> ::= E
<quit> ::= Q
<nextline> ::= <line feed>
<prevline> ::= <alt mode>
<prntdot> ::= =
<rename> ::= R<letter>
SEMANTICS:
1. "." refers to the current line, "*" refers to the last line.
2. α:β means all lines whose numbers are between α and β inclusive.
3. α!n means n lines, starting at α
4. Lines are inserted after the named line. If it is desired to
insert lines at the beginning of the text, the command I0 will
do this.
5. When the editor is in insert mode, it prompts with a "*".
Otherwise, it prompts with a "→".
6. Insertion is terminated by an alt mode. However, unlike SOS,
if the alt mode is typed at the end of a non-blank line, the
line is retained in the text.
7. Insertion does not change ".". Thus, after inserting any number
of lines, "." still points to the line after which the new
lines were inserted.
8. If the print command is given without a range, it is as if the
range ".:*" was specified.
9. The alter command gives the line to the system line editor in
a manner similar to the Z command of SOS.
10. The join command removes the carriage return and line feed
between the named line and the next line. It also decreases
the line number of all subsequent lines.
11. The find command moves the line pointer "." to the next line
which contains the string. If no such line exists, the value
of "." is unchanged. If there is no range given, the value
".:*" is used. If the string is null, the last search string is
used. The command consisting of simply "F" searches for the
previous string in the range ".+1:*".
12. When the compiler detects an error, it calls the editor with
a pointer to the location of the error. Normally, control returns
to the main calculator loop upon exit from the editor. However,
with a text function (command T above), the source would be lost,
so the compiler is recalled on exit. The quit command will exit
to the main calculator loop in any case.
13. When the command "=" is typed, the numerical value of "." is printed.
14. The rename command is used to change the name of a macro. If
a "text function" (see calculator T command) is renamed, the macro
is not executed upon exit from the editor.
THE MACRO LANGUAGE
Macros for the WISE calculator are written in an ALGOL-like
language. There are several differences, however, reflecting the
stack nature of WISE. In the following description, undefined non-
terminals are the obvious thing.
SYNTAX
<program> ::= <block> | ( <arglist> ) <block> | NOSYNC <stmt>
<block> ::= <stmt> | NEW <arglist> ; <stmt>
<arglist> ::= <vrbl> | <vrbl> , <arglist>
<vrbl> ::= A | B | C | D | E | F | G | H | I | J
<stmt> ::= <polstmt> | <gostmt> | <retstmt> | <astmt> | <pause stmt> |
<condstmt> | <forstmt> | <whlstmt> | <cmnt> | <empty> |
<compd stmt> | <expr> | <label> : <stmt>
<polstmt> ::= POL <character string not containing ;>
<gostmt> ::= GO <label> | GO TO <label>
<label> ::= <a string of letters and digits, starting with a letter, of
length≤64, but not a vrbl or reserved word>
<retstmt> ::= RETURN | RETURN ( <exprlist> )
<exprlist> ::= <expr> | <expr> , <exprlist>
<astmt> ::= <mulstor> ← <expr>
<mulstor> ::= <vrbl> | { <arglist> }
<pause stmt> ::= PAUSE <character string not containing ;>
<condstmt> ::= IF <expr> THEN <stmt> | IF <expr> THEN <stmt> ELSE <stmt>
<forstmt> ::= FOR <vrbl> ← <forlist> DO <stmt>
<forlist> ::= <forlstel> | <forlstel> , <forlist>
<forlstel> ::= <expr> | <expr> STEP <expr> UNTIL <expr> |
<expr> STEP <expr> WHILE <expr> | <expr> WHILE <expr>
<whlstmt> ::= WHILE <expr> DO <stmt>
<cmnt> ::= COMMENT <character string not containing ;>
<compd stmt> ::= BEGIN <compd tail>
<compd tail> ::= <stmt> END | <stmt> ; <compd tail>
<expr> ::= <sexp> | IF <expr> THEN <expr> ELSE <expr>
<sexp> ::= <bfac> | <sexp> ∨ <bfac>
<bfac> ::= <bsec> | <bfac> ∧ <bsec>
<bsec> ::= <relat> | ¬ <relat>
<relat> ::= <aexp> | <aexp> <relation> <aexp>
<relation> ::= < | ≤ | = | ≠ | ≥ | >
<aexp> ::= <term> | + <term> | - <term> | <aexp> + <term> | <aexp> - <term>
<term> ::= <factor> | <term> <mulop> <factor>
<mulop> ::= * | / | % | DIV | REM | MOD
<factor> ::= <primary> | <factor> ↑ <primary>
<primary> ::= TRUE | FALSE | <number> | <funcall> | PI | π | ( <expr> ) |
<macrocall> | <assign> | <vrbl> | <prompt>
<funcall> ::= <function name> | <function name> ( <exprlist> )
<function name> ::= SIN | COS| LOG | EXP | ABS | TOP | SQRT |
ARCTAN | ARCTAN2 | IN
<assign> ::= <vrbl> ← <expr>
<macrocall> ::= <letter> ( <exprlist> ) | <letter> ( )
<prompt> ::= PROMPT ( <string not containing )> )
SEMANTICS
1. A macro definition begins with an optional list of arguments.
When a program is entered, the current value of the variables
in the arglist are saved and the top n elements of the stack are
popped into the corresponding variables. The order in which the
variables are filled is from right to left. Thus if the macro
begins (A,C,G,B)... , register B will get the "top" of the stack,
G the next, etc. This makes more sense when you consider the
"push up" configuration of the stack on the screen. If you are
wondering how the old values can be saved on the stack and the
new ones obtained from it, remember that the compiled programs
have another stack available to hold the saved values until after
the arguments have been taken from the stack. At this time, the
saved values are placed on the calculator stack. The reserved
word NOSYNC inhibits saving on the stack and also inhibits
stack synchronization upon exit (see Note 5).
2. The NEW construction is implemented simply. It causes the
variables to be stacked, and then remembers to unstack them
whenever the program is exited.
3. The POL statement allows the programmer to enter any series
of characters which is passed essentially unchanged to the
compiled code. Thus any Polish string of operations can be
specified. Compiled code is a string of 9 bit characters,
reflecting the <control> and <meta> bits available on the
keyboard. To specify <control>, precede a character by α.
Precede a character by β to specify <meta>. POL statements
must be terminated by a ";".
4. The label of a GO TO statement cannot be a variable name or
a reserved word. Reserved words are all those words capitalized
in the above grammar plus a few others. Take your chances.
5. The RETURN statement specifies an exit from a macro. It
causes several things to happen, in the following order:
a. The stack is restored to its state immediately after
entry to the program (i.e., after variables were saved).
b. The expressions of the <exprlist> are evaluated and saved
on the system stack.
c. The saved register values are restored from the stack.
d. The "returned" values are recalled to the stack.
e. Control is returned to the calling program, or the main
calculator loop, if this is the top level program.
There are several important things to be noted. First, step (a)
above is accomplished simply by removing 0 or more stack entries
until the stack size corresponds to what it was on entry. The
calculator gets confused and angry when there are already too
few stack elements. For this reason, not even programs that
have no arguments or NEW variables can use up more stack entries
than they create. Macros that begin with the reserved word NOSYNC
do things differently. Since the system has saved nothing on the
stack, steps (a) & (c) are not done. Return expressions are illegal with
NOSYNC, so steps (b) & (d) are not done. In this case, the program
simply returns.
6. The multiple store option causes the top several elements of the
stack to be stored in registers. For example,
{D,G,A}← <expr>
will compile as code to evaluate <expr>, store the top of the
stack in A, the next element in G, and the third element in D.
As the values are stored, they are removed from the stack, so
in the above example, three elements would be removed from the
stack.
7. The PAUSE statement causes a message to be displayed at the
bottom of the screen and program execution to be interrupted.
Execution continues when a single character, the value of which
is ignored, is typed. Another feature of the PAUSE statement
is that it allows the user to see the state of the stack and
variables at a point during program execution. Usually, the
screen doesn't change until after the macro has exited, but
the displaying of the message causes new values of registers
and stack entries to be displayed as well. See the Q command
to the calculator (above) for further discussion.
8. Any expression can be used as a boolean value in a conditional
expression. If the expression is equal to zero, the TRUE
branch is taken. A non-zero value designates false. This
is the opposite of the scheme used by some other languages,
such as SAIL. If a truth valued expression, such as a relation,
is used in an arithmetic context, it has a value of 0 if TRUE
and 1 if FALSE.
9. In a FOR statement, the STEP expression (if present) is evaluated
twice for each time through the loop if there is an UNTIL clause.
First it is evaluated as the increment, then to be used
in determining the proper test for completion. For example,
FOR r←α STEP ε UNTIL β DO s;
is roughly equivalent to the following program:
r←α;
GO TO L2;
L1: r←r+ε;
L2: IF (r-β)*ε>0 THEN GO TO L3;
s;
GO TO L1;
L3:
10. There is a bit of redundancy in the <mulop>'s. "%" and DIV
are equivalent, and denote integer division. This means, the
number of times that the second operand will go evenly into the
first. REM and MOD are equivalent and denote the remainder
after the integer divide operation. For example,
π REM 2 = 1.1415926535897932384 .
11. The expression syntax is sufficiently similar to all other
algorithmic languages that one should have no trouble figuring
out expressions. The functions are the only thing that might
need some more explanation. It has already been mentioned above
that any arguments not supplied to functions in explicit
arguments lists are taken from the top of the stack. The
function TOP is merely a syntactic convenience to allow the
top of the stack to be used in expressions. As a one argument
function that returns that argument, it compiles as no code at
all. If you wish to duplicate the top of the stack, the fastest
way to do that is "POL =;". The IN function causes a number
to be prompted for input. It also unlocks the display as
described for the PAUSE statement.
12. The assignment statement statement causes the top of the stack
to be popped off after it is stored, but an assignment used in
an expression context is retained until the value is used. Thus
to make an assignment and also leave something on the stack,
simply enclose the outer assignment in parentheses. This obviously
won't work for multiple stores.
13. The PROMPT function is similar to the IN function with the difference
being that the user supplies the desired prompt. All characters
between the parentheses (up to 39 of them) are displayed at the
bottom of the screen and the number typed in is returned as the value.
LANGUAGE SUMMARY
The following is an informal summary of the macro language
facility in WISE. Let the following abbreviations apply in the summary:
s - a statement
e - an expression
r - a storable register (A-J)
d - a digit
PROGRAM:
s
(r,...,r) s
NEW r,...,r; s
(r,...,r) NEW r,...,r; s
NOSYNC s
STATEMENT:
POL ... ;
GO label
GO TO label
RETURN
RETURN (e,...,e)
r←e
{r,...,r}←e
PAUSE ... ;
IF e THEN s
IF e THEN s ELSE s
FOR r←e STEP e UNTIL e DO s
FOR r←e STEP e WHILE e DO s
FOR r←e WHILE e DO s
FOR r←e,...,e DO s
FOR r←<any combination of the above> DO s
WHILE e DO s
COMMENT ... ;
BEGIN s;...s END
e
label: s
<empty>
CONSTANTS:
dddddddd
ddddddd.dddd
ddddEdd
dddd.ddEdd
dddE-dd
ddd.ddE-dd
TRUE
FALSE
PI
π
FUNCTIONS:
SIN
COS
LOG
EXP
ABS
TOP
SQRT
ARCTAN
ARCTAN2
IN
PROMPT(...)
OPERATORS: (in order of increasing precedence)
∨
∧
¬
< ≤ = ≠ ≥ >
+ -
* / % DIV REM MOD
↑